// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2025-03-28

package middlewares

import (
	"encoding/json"
	"fmt"
	"gitee.com/go-libs/log"
	"github.com/gin-gonic/gin"
	"net/http"
	"regexp"
	"time"
)

// Tracing 请求链.
func Tracing(c *gin.Context) {
	var (
		span = log.NewSpan(c.Request.URL.Path)
		ctx  = span.GetContext()
		t    = time.Now()
		text = fmt.Sprintf(`method="%s", uri="%s"`, c.Request.Method, c.Request.URL.Path)
	)

	c.Request = c.Request.WithContext(ctx)

	// 1. 请求头部.
	if len(c.Request.Header) > 0 {
		buf, _ := json.Marshal(c.Request.Header)
		text += fmt.Sprintf(`, header=%s`, buf)
	}

	// 2. 请求入参.
	switch c.Request.Method {
	case http.MethodPost, http.MethodPut, http.MethodPatch:
		if buf, err := c.GetRawData(); err == nil {
			text += fmt.Sprintf(`, body=%s`, regexp.MustCompile(`\n\s*`).ReplaceAllString(string(buf), ""))
		}
	}

	// 3. 监听结束.
	defer func() {
		log.Infofc(ctx, `request end: duration="%dus"`, time.Now().Sub(t).Microseconds())
		span.End()
	}()

	// 3. 链式调用.
	log.Infofc(ctx, `request begin: %s`, text)
	c.Header("X-Request-Id", span.GetTracing().GetTraceId().String())
	c.Next()
}
